﻿/********************************************************************************
    Copyright (C) Binod Nepal, Planet Earth Solutions Pvt. Ltd., Kathmandu.
	Released under the terms of the GNU General Public License, GPL, 
	as published by the Free Software Foundation, either version 3 
	of the License, or (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
    See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
***********************************************************************************/

using System;
using System.Web;
using System.Drawing;
using System.IO;
using System.Web.SessionState;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Drawing.Drawing2D;

namespace MixNP.Web.Handlers
{
    /// <summary>
    /// Summary description for Captcha
    /// </summary>
    public class Captcha : IHttpHandler, IReadOnlySessionState
    {

        public void ProcessRequest(HttpContext context)
        {
            int iHeight = 80;
            int iWidth = 190;
            Random oRandom = new Random();

            int[] aBackgroundNoiseColor = new int[] { 150, 150, 150 };
            int[] aTextColor = new int[] { 0, 0, 0 };
            int[] aFontEmSizes = new int[] { 15, 20, 25, 30, 35 };

            string[] aFontNames = new string[]
                                                {
                                                 "Comic Sans MS",
                                                 "Arial",
                                                 "Times New Roman",
                                                 "Georgia",
                                                 "Verdana",
                                                 "Geneva"
                                                };
            FontStyle[] aFontStyles = new FontStyle[]
                                                {  
                                                 FontStyle.Bold,
                                                 FontStyle.Italic,
                                                 FontStyle.Regular,
                                                 FontStyle.Strikeout,
                                                 FontStyle.Underline
                                                };
            HatchStyle[] aHatchStyles = new HatchStyle[]
                                                {
                                                    HatchStyle.BackwardDiagonal, HatchStyle.Cross, 
	                                                HatchStyle.DashedDownwardDiagonal, HatchStyle.DashedHorizontal,
                                                    HatchStyle.DashedUpwardDiagonal, HatchStyle.DashedVertical, 
	                                                HatchStyle.DiagonalBrick, HatchStyle.DiagonalCross,
                                                    HatchStyle.Divot, HatchStyle.DottedDiamond, HatchStyle.DottedGrid, 
	                                                HatchStyle.ForwardDiagonal, HatchStyle.Horizontal,
                                                    HatchStyle.HorizontalBrick, HatchStyle.LargeCheckerBoard, 
	                                                HatchStyle.LargeConfetti, HatchStyle.LargeGrid,
                                                    HatchStyle.LightDownwardDiagonal, HatchStyle.LightHorizontal, 
	                                                HatchStyle.LightUpwardDiagonal, HatchStyle.LightVertical,
                                                    HatchStyle.Max, HatchStyle.Min, HatchStyle.NarrowHorizontal, 
	                                                HatchStyle.NarrowVertical, HatchStyle.OutlinedDiamond,
                                                    HatchStyle.Plaid, HatchStyle.Shingle, HatchStyle.SmallCheckerBoard, 
	                                                HatchStyle.SmallConfetti, HatchStyle.SmallGrid,
                                                    HatchStyle.SolidDiamond, HatchStyle.Sphere, HatchStyle.Trellis, 
	                                                HatchStyle.Vertical, HatchStyle.Wave, HatchStyle.Weave,
                                                    HatchStyle.WideDownwardDiagonal, HatchStyle.WideUpwardDiagonal, HatchStyle.ZigZag
                                                };

            //Get Captcha in Session
            string sCaptchaText = context.Session["Captcha"].ToString();

            //Creates an output Bitmap
            Bitmap oOutputBitmap = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb);
            Graphics oGraphics = Graphics.FromImage(oOutputBitmap);
            oGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;

            //Create a Drawing area
            RectangleF oRectangleF = new RectangleF(0, 0, iWidth, iHeight);
            Brush oBrush = default(Brush);

            //Draw background (Lighter colors RGB 100 to 255)
            oBrush = new HatchBrush(aHatchStyles[oRandom.Next
                (aHatchStyles.Length - 1)], Color.FromArgb((oRandom.Next(100, 255)),
                (oRandom.Next(100, 255)), (oRandom.Next(100, 255))), Color.White);
            oGraphics.FillRectangle(oBrush, oRectangleF);

            System.Drawing.Drawing2D.Matrix oMatrix = new System.Drawing.Drawing2D.Matrix();
            int i = 0;
            for (i = 0; i <= sCaptchaText.Length - 1; i++)
            {
                oMatrix.Reset();
                int iChars = sCaptchaText.Length;
                int x = iWidth / (iChars + 1) * i;
                int y = iHeight / 2;

                //Rotate text Random
                oMatrix.RotateAt(oRandom.Next(-40, 40), new PointF(x, y));
                oGraphics.Transform = oMatrix;

                //Draw the letters with Random Font Type, Size and Color
                oGraphics.DrawString
                (
                    //Text
                sCaptchaText.Substring(i, 1),
                    //Random Font Name and Style
                new Font(aFontNames[oRandom.Next(aFontNames.Length - 1)],
                   aFontEmSizes[oRandom.Next(aFontEmSizes.Length - 1)],
                   aFontStyles[oRandom.Next(aFontStyles.Length - 1)]),
                    //Random Color (Darker colors RGB 0 to 100)
                new SolidBrush(Color.FromArgb(oRandom.Next(0, 100),
                   oRandom.Next(0, 100), oRandom.Next(0, 100))),
                x,
                oRandom.Next(10, 40)
                );
                oGraphics.ResetTransform();
            }

            MemoryStream oMemoryStream = new MemoryStream();
            oOutputBitmap.Save(oMemoryStream, System.Drawing.Imaging.ImageFormat.Png);
            byte[] oBytes = oMemoryStream.GetBuffer();

            oOutputBitmap.Dispose();
            oMemoryStream.Close();

            context.Response.BinaryWrite(oBytes);
            context.Response.End();
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}